package com.ktg.mes.chanjet.controller;

import cn.hutool.json.JSONObject;
import com.chanjet.openapi.sdk.java.ChanjetClient;
import com.chanjet.openapi.sdk.java.domain.GetAppAccessTokenContent;
import com.chanjet.openapi.sdk.java.domain.GetOrgAccessTokenContent;
import com.chanjet.openapi.sdk.java.domain.GetPermanentAuthCodeContent;
import com.chanjet.openapi.sdk.java.domain.GetTokenByPermanentCodeContent;
import com.chanjet.openapi.sdk.java.exception.ChanjetApiException;
import com.chanjet.openapi.sdk.java.response.*;
import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;
import com.ktg.common.annotation.Log;
import com.ktg.common.core.domain.Result;
import com.ktg.common.enums.BusinessType;
import com.ktg.mes.chanjet.common.Constants;
import com.ktg.mes.chanjet.config.OpenApiConfig;
import com.ktg.mes.chanjet.content.InventoryClassContent;
import com.ktg.mes.chanjet.dto.ChanjetEncryptMsg;
import com.ktg.mes.chanjet.request.AppTicketRequest;
import com.ktg.mes.chanjet.response.AppTicketResponse;
import com.ktg.mes.chanjet.response.InventoryClassResponse;
import com.ktg.mes.chanjet.spi.ChanjetSpi;
import com.ktg.mes.chanjet.utils.AESUtils;
import com.ktg.mes.unit.other.RedisService;
import io.swagger.annotations.ApiOperation;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@Slf4j
@RequestMapping("/chanjet/message")
public class MessageController {


    @Autowired
    ApplicationContext applicationContext;

    @Autowired
    private OpenApiConfig openApiConfig;

    @Autowired
    private ChanjetClient chanjetClient;

    @Autowired
    private ChanjetSpi chanjetSpi;

    @Autowired
    private RedisService redisService;

    /**
     * OAuth回调地址接口
     *
     * @param code 开放平台的授权码
     * @return
     * @throws ChanjetApiException
     */
    @ApiOperation(value = "OAuth回调地址接口", httpMethod = "GET")
    @Log(title = "开放平台回调信息",businessType = BusinessType.GRANT)
    @GetMapping("receiveCode")
    public Map<String, String> receiveCode(@RequestParam("code") String code) throws ChanjetApiException {
        GetTokenResponse response = chanjetSpi.getToken(code, openApiConfig.getRedirectUri());
        Map<String, String> map = new HashMap<>();
        String status = response.getCode();
        if (!status.equals("200")) {
            log.error("获取开放平台token失败");
            map.put(Constants.RESULT, Constants.FAIL);
            return map;
        }
        GetTokenResponse.Result result = response.getResult();
        UserResponse user = chanjetSpi.user(result.getAccessToken());
        redisService.add(Constants.CHANJET_TOKEN+"_user",user);
        redisService.add(Constants.REFRESH_TOKNE, result.getRefreshToken(), 1000 * 60 * 10, TimeUnit.MINUTES);
        redisService.add(Constants.CHANJET_TOKEN, result.getAccessToken(), 1000 * 60 * 10, TimeUnit.MINUTES);
        redisService.add(Constants.CHANJET_PERMANENT_CODE, result.getUserAuthPermanentCode());
        log.info("已将用户临时授权码和token到redis中");
        // 推送appTicket
        AppTicketRequest appTicketRequest = new AppTicketRequest();
        appTicketRequest.setAppKey(openApiConfig.getAppKey());
        appTicketRequest.setAppSecret(openApiConfig.getAppSecret());
        appTicketRequest.setRequestUri("/auth/appTicket/resend");
        AppTicketResponse appTicketResponse = chanjetClient.execute(appTicketRequest);
        if(appTicketResponse.getCode().equals("200")){
            log.info("请求推送appTicket消息成功！");
        }else{
            log.error("请求推送appTicket消息失败");
        }
        map.put(Constants.RESULT, Constants.SUCCESS);
        return map;
    }

    @PostMapping("receive")
    @Log(title = "开放平台接收信息")
    @ApiOperation("接收信息")
    public Object receive(@RequestBody ChanjetEncryptMsg chanjetEncryptMsg) {
        Map<String, String> responseMap = new HashMap<>();
        try {
            String encryptMsg = chanjetEncryptMsg.getEncryptMsg();
            log.info("解密前的消息{}", encryptMsg);
            String msg = AESUtils.aesDecrypt(encryptMsg, openApiConfig.getSecret());
            log.info("解密后消息{}", msg);

            Map map = new Gson().fromJson(msg, Map.class);
            String msgType = (String) map.get(Constants.MSG_TYPE);
            log.info(map.toString());
            //appKey不匹配返回fail
            if (!openApiConfig.getAppKey().equals(map.get(Constants.APP_KEY))) {
                responseMap.put(Constants.RESULT, Constants.FAIL);
                return responseMap;
            }
            verifyMsgType(msgType, map);
            //直接返回结果
            responseMap.put(Constants.RESULT, Constants.SUCCESS);
            return responseMap;
        } catch (Exception e) {
            log.error("解析消息失败", e);
            responseMap.put(Constants.RESULT, Constants.FAIL);
            return responseMap;
        }
    }

    private void verifyMsgType(String msgType, Map map) throws ChanjetApiException {
        switch (msgType) {
            case "TEMP_AUTH_CODE": //临时授权码
                GetPermanentAuthCodeContent content = new GetPermanentAuthCodeContent();
                Map bizContent = (LinkedTreeMap) map.get("bizContent");
                redisService.add(Constants.CHANJET_TEMP_CODE, (String) bizContent.get("tempAuthCode"), 1000 * 60 * 10, TimeUnit.MINUTES);
                break;
            case "APP_TICKET":   // app_ticket信息
                //todo 等应用开通后续开发
//                Map app_ticket = (LinkedTreeMap)map.get("bizContent");
//                redisService.add(Constants.APP_TICKET,(String)app_ticket.get("appTicket"));
//                GetAppAccessTokenContent appTicketContent = new GetAppAccessTokenContent();
//                appTicketContent.setAppTicket((String)app_ticket.get("appTicket"));
//                GetAppAccessTokenResponse appAccessTokenResponse = chanjetSpi.getAppAccessToken(appTicketContent);
//                // 获取应用凭证
//                GetAppAccessTokenResponse.Result result = appAccessTokenResponse.getResult();
//                String appAccessToken = result.getAppAccessToken();
//                // 获取企业永久授权码
//                GetPermanentAuthCodeContent permanentAuthCodeContent = new GetPermanentAuthCodeContent();
//                permanentAuthCodeContent.setTempAuthCode(Constants.CHANJET_TEMP_CODE);
//                permanentAuthCodeContent.setAppAccessToken(appAccessToken);
//                GetPermanentAuthCodeResponse permanentAuthCodeResponse = chanjetSpi.getPermanentAuthCode(permanentAuthCodeContent);
//                GetPermanentAuthCodeResponse.Result permanentAuthCodeResult = permanentAuthCodeResponse.getResult();
//                String permanentAuthCode = permanentAuthCodeResult.getPermanentAuthCode();
//                redisService.add(Constants.CHANJET_ORG_PERMANENT_CODE,permanentAuthCode);
//                //获取企业应用凭证
//                GetOrgAccessTokenContent orgAccessTokenContent = new GetOrgAccessTokenContent();
//                orgAccessTokenContent.setAppAccessToken(appAccessToken);
//                orgAccessTokenContent.setPermanentAuthCode(Constants.CHANJET_ORG_PERMANENT_CODE);
//                GetOrgAccessTokenResponse orgAccessTokenResponse = chanjetSpi.getOrgAccessToken(orgAccessTokenContent);
//                GetOrgAccessTokenResponse.Result orgAccessTokenResult = orgAccessTokenResponse.getResult();
//                String orgAccessToken = orgAccessTokenResult.getOrgAccessToken();
//                //永久授权码获取token
//                GetTokenByPermanentCodeContent tokenByPermanentCodeContent = new GetTokenByPermanentCodeContent();
//                tokenByPermanentCodeContent.setOrgAccessToken(orgAccessToken);
//                tokenByPermanentCodeContent.setUserAuthPermanentCode(Constants.CHANJET_ORG_PERMANENT_CODE);
//                GetTokenByPermanentCodeResponse tokenByPermanentCodeResponse = chanjetSpi.getTokenByPermanentCode(tokenByPermanentCodeContent);
//                GetTokenByPermanentCodeResponse.Result tokenByPermanentCodeResult = tokenByPermanentCodeResponse.getResult();
//                redisService.add(Constants.CHANJET_TOKEN,tokenByPermanentCodeResult.getAccessToken());
                break;
        }
    }

}
